package com.mcxx.util;

import org.apache.commons.lang3.StringUtils;
import java.beans.PropertyEditorSupport;
import java.sql.Timestamp;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class DateUtil extends PropertyEditorSupport {

    public static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    public static SimpleDateFormat sdf2 = new SimpleDateFormat("yyyy-MM-dd");
    public static SimpleDateFormat sdf4 = new SimpleDateFormat("yyyy/MM/dd");
    public static SimpleDateFormat sdfYM = new SimpleDateFormat("yyyyMM");
    public static  SimpleDateFormat sdf5 = new SimpleDateFormat("yyyyMM");
    public static SimpleDateFormat sdf6 = new SimpleDateFormat("yyyyMMdd");

    public static ThreadLocal<SimpleDateFormat> date_sdf = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd");
        }
    };
    public static ThreadLocal<SimpleDateFormat> yyyyMMdd = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMdd");
        }
    };
    public static ThreadLocal<SimpleDateFormat> date_sdf_wz = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy年MM月dd日");
        }
    };
    public static ThreadLocal<SimpleDateFormat> time_sdf = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm");
        }
    };
    public static ThreadLocal<SimpleDateFormat> yyyymmddhhmmss = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyyMMddHHmmss");
        }
    };
    public static ThreadLocal<SimpleDateFormat> short_time_sdf = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("HH:mm");
        }
    };
    public static ThreadLocal<SimpleDateFormat> datetimeFormat = new ThreadLocal<SimpleDateFormat>() {
        @Override
        protected SimpleDateFormat initialValue() {
            return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        }
    };


    private static final long DAY_IN_MILLIS = 24 * 3600 * 1000;
    private static final long HOUR_IN_MILLIS = 3600 * 1000;
    private static final long MINUTE_IN_MILLIS = 60 * 1000;
    private static final long SECOND_IN_MILLIS = 1000;


    public static String getCurrentDate() {
        Calendar c = Calendar.getInstance();
        Date date = c.getTime();
        SimpleDateFormat simple = new SimpleDateFormat("yyyy-MM-dd");
        return simple.format(date);
    }


    public static String getMonthString() {
        Date date = new Date();
        return sdfYM.format(date);
    }


    public static long getMonthEndDateLong() {
        Calendar cale = Calendar.getInstance();
        //cale.set(Calendar.DAY_OF_MONTH,0);
        cale.set(Calendar.DAY_OF_MONTH, cale.getActualMaximum(Calendar.DAY_OF_MONTH));
        return cale.getTimeInMillis();
    }

    public static Integer getAgeByMonthEndDate(String birthday) {
        Integer ss = 0;
        if (CommonUtil.invalidArgs(birthday)) {
            return ss;
        }
        Date date = null;
        try {
            if (birthday.indexOf("-") != -1) {
                date = sdf2.parse(birthday);
            } else if (birthday.indexOf("/") != -1) {
                date = sdf4.parse(birthday);
            }
            Long now = getMonthEndDateLong();
            long cha = now - date.getTime();
            long age = cha / 365 / 24 / 60 / 60 / 1000;
            ss = Integer.parseInt(String.valueOf(age));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return ss;
    }

    public static String DateToString3(Date date){
        return sdf6.format(date);
    }


    public static long dateDiff(Date beginDate, Date endDate){
        return (endDate.getTime()-beginDate.getTime())/(24*60*60*1000);
    }


    public static Boolean compare(Date date1, Date date2) throws ParseException {
        date1 = sdf.parse(sdf.format(date1));
        date2 = sdf.parse(sdf.format(date2));
        return date1.before(date2);
    }


    public static int calDiffMonth(String startDate,String endDate) {
        int result=0;

        int startYear= Integer.parseInt(startDate.substring(0,4));
        int startMonth=Integer.parseInt(startDate.substring(4,6));
        int endYear=Integer.parseInt(endDate.substring(0,4));
        int endMonth=Integer.parseInt(endDate.substring(4,6));

        result = (endYear - startYear) * 12  +   (endMonth - startMonth);

        return result;
    }

    public static void main(String[] args) throws ParseException {
        System.out.println(DateUtil.sdf6.parse("20120901"));
    }


    public static Boolean compareMonth(String month1, String month2) {
        Boolean result = false;
        if(StringUtils.isEmpty(month1) || StringUtils.isEmpty(month2)) {
            return result;
        }
        try {
            if (month1.equals(month2)) {
                result = true;
            } else {
                Date date1 = sdf6.parse(month1.concat("01"));
                Date date2 = sdf6.parse(month2.concat("01"));
                if (date1.after(date2)) {
                    result = true;
                }
            }
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return result;
    }


    private static SimpleDateFormat getSDFormat(String pattern) {
        return new SimpleDateFormat(pattern);
    }


    public static Calendar getCalendar() {
        return Calendar.getInstance();
    }


    public static Calendar getCalendar(long millis) {
        Calendar cal = Calendar.getInstance();

        cal.setTime(new Date(millis));
        return cal;
    }







    public static Date getDate() {
        return new Date();
    }


    public static String getLastMonth() {
        Calendar c = Calendar.getInstance();
        c.add(Calendar.MONTH, -1);
        Date m2 = c.getTime();
        return sdf5.format(m2);
    }


    public static String reduceMonth(String dateStr, int m) {
        Calendar c = Calendar.getInstance();
        try {

            c.setTime(yyyyMMdd.get().parse(dateStr + "01"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.add(Calendar.MONTH, -m);
        Date m2 = c.getTime();
        return sdf5.format(m2);
    }

    public static String addMonth(String dateStr, int m) {
        Calendar c = Calendar.getInstance();
        try {

            c.setTime(yyyyMMdd.get().parse(dateStr + "01"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.add(Calendar.MONTH, +m);
        Date m2 = c.getTime();
        return sdf5.format(m2);
    }


    public static Date reduceMonthDate(String dateStr, int m) {
        Calendar c = Calendar.getInstance();
        try {

            c.setTime(yyyyMMdd.get().parse(dateStr + "01"));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.add(Calendar.MONTH, -m);
        Date m2 = c.getTime();
        try {
            m2 = sdf2.parse(sdf2.format(m2));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return m2;
    }



    public static String reduceMonths(String dateStr, int m) {
        return "";
    }

    public static String reduceMonthb(String dateStr, int m) {
        return "";
    }

    public static Date reduceMonthb(Date dateStr, int m) {
        Date rstDate = new Date();
        return rstDate;
    }


    public static Date getDate(long millis) {
        return new Date(millis);
    }


    public static String timestamptoStr(Timestamp time) {
        Date date = null;
        if (null != time) {
            date = new Date(time.getTime());
        }
        return date2Str(date_sdf.get());
    }


    public static Timestamp str2Timestamp(String str) {
        Date date = str2Date(str, date_sdf.get());
        return new Timestamp(date.getTime());
    }


    public static Date str2Date(String str, SimpleDateFormat sdf) {
        if (null == str || "".equals(str)) {
            return null;
        }
        Date date = null;
        try {
            date = sdf.parse(str);
            return date;
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }


    public static String date2Str(SimpleDateFormat date_sdf) {
        Date date = getDate();
        if (null == date) {
            return null;
        }
        return date_sdf.format(date);
    }


    public static String dateformat(String date, String format) {
        SimpleDateFormat sformat = new SimpleDateFormat(format);
        Date _date = null;
        try {
            _date = sformat.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return sformat.format(_date);
    }


    public static String date2Str(Date date, SimpleDateFormat date_sdf) {
        if (null == date) {
            return null;
        }
        return date_sdf.format(date);
    }


    public static String getDate(String format) {
        Date date = new Date();
        if (null == date) {
            return null;
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(date);
    }


    public static Timestamp getTimestamp(long millis) {
        return new Timestamp(millis);
    }


    public static Timestamp getTimestamp(String time) {
        return new Timestamp(Long.parseLong(time));
    }


    public static Timestamp getTimestamp() {
        return new Timestamp(System.currentTimeMillis());
    }


    public static String now() {
        return datetimeFormat.get().format(getCalendar().getTime());
    }


    public static Timestamp getTimestamp(Date date) {
        return new Timestamp(date.getTime());
    }


    public static Timestamp getCalendarTimestamp(Calendar cal) {

        return new Timestamp(cal.getTime().getTime());
    }

    public static Timestamp gettimestamp() {
        Date dt = new Date();
        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowTime = df.format(dt);
        Timestamp buydate = Timestamp.valueOf(nowTime);
        return buydate;
    }







    public static long getMillis() {
        return System.currentTimeMillis();
    }


    public static long getMillis(Calendar cal) {

        return cal.getTime().getTime();
    }


    public static long getMillis(Date date) {
        return date.getTime();
    }


    public static long getMillis(Timestamp ts) {
        return ts.getTime();
    }







    public static String formatDate() {
        return date_sdf.get().format(getCalendar().getTime());
    }


    public static String formatDateTime() {
        return datetimeFormat.get().format(getCalendar().getTime());
    }


    public static String getDataString(SimpleDateFormat formatstr) {
        return formatstr.format(getCalendar().getTime());
    }


    public static String formatDate(Calendar cal) {
        return date_sdf.get().format(cal.getTime());
    }


    public static String formatDate(Date date) {
        return date_sdf.get().format(date);
    }


    public static String formatDate(long millis) {
        return date_sdf.get().format(new Date(millis));
    }


    public static String formatDate(String pattern) {
        return getSDFormat(pattern).format(getCalendar().getTime());
    }


    public static String formatDate(Calendar cal, String pattern) {
        return getSDFormat(pattern).format(cal.getTime());
    }


    public static String formatDate(Date date, String pattern) {
        return getSDFormat(pattern).format(date);
    }







    public static String formatTime() {
        return time_sdf.get().format(getCalendar().getTime());
    }


    public static String formatTime(long millis) {
        return time_sdf.get().format(new Date(millis));
    }


    public static String formatTime(Calendar cal) {
        return time_sdf.get().format(cal.getTime());
    }


    public static String formatTime(Date date) {
        return time_sdf.get().format(date);
    }







    public static String formatShortTime() {
        return short_time_sdf.get().format(getCalendar().getTime());
    }


    public static String formatShortTime(long millis) {
        return short_time_sdf.get().format(new Date(millis));
    }


    public static String formatShortTime(Calendar cal) {
        return short_time_sdf.get().format(cal.getTime());
    }


    public static String formatShortTime(Date date) {
        return short_time_sdf.get().format(date);
    }









    public static Date parseDate(String src, String pattern) throws ParseException {
        return getSDFormat(pattern).parse(src);

    }


    public static Calendar parseCalendar(String src, String pattern) throws ParseException {

        Date date = parseDate(src, pattern);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        return cal;
    }

    public static String formatAddDate(String src, String pattern, int amount) throws ParseException {
        Calendar cal;
        cal = parseCalendar(src, pattern);
        cal.add(Calendar.DATE, amount);
        return formatDate(cal);
    }


    public static Timestamp parseTimestamp(String src, String pattern) throws ParseException {
        Date date = parseDate(src, pattern);
        return new Timestamp(date.getTime());
    }







    public static int dateDiff(char flag, Calendar calSrc, Calendar calDes) {

        long millisDiff = getMillis(calSrc) - getMillis(calDes);

        if (flag == 'y') {
            return (calSrc.get(Calendar.YEAR) - calDes.get(Calendar.YEAR));
        }

        if (flag == 'd') {
            return (int) (millisDiff / DAY_IN_MILLIS);
        }

        if (flag == 'h') {
            return (int) (millisDiff / HOUR_IN_MILLIS);
        }

        if (flag == 'm') {
            return (int) (millisDiff / MINUTE_IN_MILLIS);
        }

        if (flag == 's') {
            return (int) (millisDiff / SECOND_IN_MILLIS);
        }

        return 0;
    }

    public static int getYear() {
        GregorianCalendar calendar = new GregorianCalendar();
        calendar.setTime(getDate());
        return calendar.get(Calendar.YEAR);
    }


    public static boolean inCurrentMonth(Date date) {
        GregorianCalendar calDate = new GregorianCalendar();
        calDate.setTime(date);

        GregorianCalendar calCurrent = new GregorianCalendar();
        calCurrent.setTime(getDate());

        if(calDate.get(Calendar.YEAR) == calCurrent.get(Calendar.YEAR)) {
            if(calDate.get(Calendar.MONTH) == calCurrent.get(Calendar.MONTH)) {
                return true;
            }
        }
        return false;
    }


    public static boolean inSameMonth(Date date, Date dateDiff) {
        if(null == date || dateDiff == null) {
            return false;
        }

        GregorianCalendar calDate = new GregorianCalendar();
        calDate.setTime(date);

        GregorianCalendar calCurrent = new GregorianCalendar();
        calCurrent.setTime(dateDiff);

        if(calDate.get(Calendar.YEAR) == calCurrent.get(Calendar.YEAR)) {
            if(calDate.get(Calendar.MONTH) == calCurrent.get(Calendar.MONTH)) {
                return true;
            }
        }
        return false;
    }


    public static String getLastDay(String yearMonth) {
        Date theDate = str2Date(yearMonth + "-01", sdf2);
        Calendar thisMonthEndDateCal = Calendar.getInstance();
        thisMonthEndDateCal.setTime(theDate);

        thisMonthEndDateCal.set(Calendar.DAY_OF_MONTH, thisMonthEndDateCal.getActualMaximum(Calendar.DAY_OF_MONTH));
        String thisMonthEndTime = sdf2.format(thisMonthEndDateCal.getTime());

        return thisMonthEndTime;

    }
}
